import datetime
import os
import sqlite3
from flask import Flask, render_template, request, redirect, url_for, session
from werkzeug.security import generate_password_hash, check_password_hash
import json
import random
import flask_cors
import requests
import threading
import time

import config

app = Flask(__name__)
flask_cors.CORS(app)
app.secret_key = os.urandom(24)

session_map = {}
# Database connection
conn = sqlite3.connect('./user_db/accounts_system.sqlite')
c = conn.cursor()

# 如果没有表，则创建表,字段 user_id, username, password,contact , 
# last_login_time=NULL, last_login_ip=NULL
c.execute('''CREATE TABLE IF NOT EXISTS users
             (user_id INTEGER PRIMARY KEY AUTOINCREMENT,
             username TEXT NOT NULL,
             password TEXT NOT NULL,
             contact TEXT,
             last_login_time TEXT,
             last_login_ip TEXT,
             mail TEXT
          )''')
#print(c.fetchall())
c.close()

captures = {}

def get_remote_ip():
    if request.headers.getlist("X-Forwarded-For"):
        return request.headers.getlist("X-Forwarded-For")[0]
    else:
        return request.remote_addr


limit_map = {}

# 判断指定IP在一分钟内的指定接口访问次数是否超过限制
def ip_limit(ip, api_name, limit=10):
    if ip not in limit_map:
        limit_map[ip] = {
            api_name: 0
        }
        return True
    elif api_name not in limit_map[ip]:
        limit_map[ip][api_name] = 0
        return True
    else:
        limit_map[ip][api_name] += 1
        return limit_map[ip][api_name] <= limit

# 定时清除limit_map
def clear_limit_map():
    while True:
        time.sleep(60)
        limit_map.clear()

t_for_clear_limit_map = threading.Thread(target=clear_limit_map)
t_for_clear_limit_map.start()

# 注册页面
@app.route('/register', methods=['GET', 'POST'])
def register():
    if not ip_limit(get_remote_ip(),'register', 3):
        return json.dumps({'status': 'error', 'error': '请求次数过多，请稍后再试'})

    if request.method == 'POST':
        json_obj = json.loads(request.data.decode('utf-8'))
        username = json_obj['username']
        password = json_obj['password']
        email = json_obj['email']

        conn = sqlite3.connect('./user_db/accounts_system.sqlite')
        c = conn.cursor()

        # 获取验证码
        captcha = json_obj['captcha']
        if captcha != captures.get(get_remote_ip()):
            return json.dumps({'status': 'error', 'error': '验证码错误'})
        # 验证用户名是否存在
        c.execute("SELECT * FROM users WHERE username=?", (username,))
        user = c.fetchone()
        if user:
            return json.dumps({'status': 'error', 'error': '用户名已存在'})
        else:

            # 加密密码
            # hashed_password = generate_password_hash(password)
            # 插入用户信息
            last_login_time = str(datetime.datetime.now())
            last_login_ip = get_remote_ip()
            c.execute("""INSERT INTO users (
                    username,
                    password,
                    contact, 
                    last_login_time,
                    last_login_ip,
                    mail) VALUES (?,?,?,?,?,?)""", 
                      (username, password, email, last_login_time, last_login_ip,email))
            conn.commit()
            return json.dumps({'status': 'ok'})
    else:
        return render_template('register.html')

# 登录页面
@app.route('/login', methods=['GET', 'POST'])
def login():
    if not ip_limit(get_remote_ip(), 'login'):
        return json.dumps({'status': 'error', 'error': '请求次数过多，请稍后再试'})

    if request.method == 'POST':
        json_obj = json.loads(request.data)
        username = json_obj['username']
        # 用户名不加密
        password = json_obj['password']
        # 验证用户名和密码是否匹配
        conn = sqlite3.connect('./user_db/accounts_system.sqlite')
        c = conn.cursor()
        c.execute("SELECT * FROM users WHERE username=? and password=? OR mail=? and password=?", (username, password,username,password))
        user = c.fetchone()
        print(user)
        if user:
            # 登录成功，设置session
            session_code = str(random.randint(100000, 999999))
            session_map[session_code] = {'username': user[1], 'user_id': user[0]}
            print(session_map[session_code])
            # 更新登录时间和IP
            last_login_time = str(datetime.datetime.now())
            last_login_ip = get_remote_ip()
            c.execute("UPDATE users SET last_login_time=?, last_login_ip=? WHERE user_id=?", (last_login_time, last_login_ip, user[0]))
            conn.commit()
            return json.dumps({'status': 'ok','session_code': session_code})
        else:
            return json.dumps({'status': 'error', 'error': '用户名或密码错误'})
    else:
        return render_template('login.html')  # 登录页面

# 邮箱验证码获取页面
@app.route('/get_captcha', methods=['POST'])
def get_captcha():
    if not ip_limit(get_remote_ip(), 'get_captcha', 60):
        return json.dumps({'status': 'error', 'error': '请求次数过多，请稍后再试'})
    # 随机生成验证码
    captcha = str(random.randint(1000, 9999))
    # 保存验证码到session
    captures[get_remote_ip()] = captcha
    print(request.data.decode('utf-8'))
    to = json.loads(request.data.decode('utf-8'))['to']
    # 发送验证码到邮箱
    r_post = requests.post(config.mail_server + "/api/v1/send_mail", data=(
        json.dumps({'send_to': to, 'subject': '验证码发送', 'content': '验证码 ' + captcha})
    ))
    # print(r_post.text)
    return r_post.text

# 获取反人机自动化操作验证码，返回的是图片数据
@app.route('/get_anti_captcha', methods=['GET'])
def get_anti_captcha():
    # 随机生成验证码
    captcha = str(random.randint(1000, 9999))
    # 保存验证码到session
    captures[get_remote_ip()] = captcha
    # 生成验证码图片
    from PIL import Image, ImageDraw, ImageFont
    import io  # 添加缺失的io导入
    img = Image.new('RGB', (100, 30), (255, 255, 255))
    draw = ImageDraw.Draw(img)
    # 字体选用默认字体
    font = ImageFont.load_default()
    draw.text((10, 10), captcha, font=font, fill=(0, 0, 0))
    img_byte_arr = io.BytesIO()
    img.save(img_byte_arr, format='PNG')
    img_byte_arr = img_byte_arr.getvalue()
    return img_byte_arr, 200, {'Content-Type': 'image/png'}

# 调取用户信息页面
@app.route('/get_user_info', methods=['POST'])
def get_user_info():
    # 获取session数据
    session_code = json.loads(request.data.decode('utf-8'))['session_code']
    if session_code in session_map:
        # 调用数据库查询除了密码以外的其他信息
        conn = sqlite3.connect('./user_db/accounts_system.sqlite')
        c = conn.cursor()
        print(session_map[session_code]['username'])
        c.execute("SELECT * FROM users WHERE username=?", (session_map[session_code]['username'],))
        # 返回的数据格式为字典，移除密码字段
        user = c.fetchone()
        user_info = {'user_id': user[0], 'username': user[1], 'contact': user[3], 'last_login_time': user[4], 'last_login_ip': user[5], 'email': user[6]}
        return json.dumps({'status': 'ok', 'user_info': user_info})
    else:
        return json.dumps({'status': 'error', 'error': '请先登录'})

# 退出登录
@app.route('/logout', methods=['POST'])
def logout():
    # 获取session数据
    session_code = json.loads(request.data.decode('utf-8'))['session_code']
    if session_code in session_map:
        # 销毁session
        del session_map[session_code]
        return json.dumps({'status': 'ok'})
    else:
        return json.dumps({'status': 'error', 'error': '请先登录'})
    
# 使用邮箱验证码登录
@app.route('/email_login', methods=['POST'])
def login_by_mail():
    if not ip_limit(get_remote_ip(), 'login_by_mail', 3):
        return json.dumps({'status': 'error', 'error': '请求次数过多，请稍后再试'})
    json_obj = json.loads(request.data.decode('utf-8'))
    email = json_obj['email']
    captcha = json_obj['captcha']
    # 验证验证码是否正确
    if captcha != captures.get(get_remote_ip()):
        return json.dumps({'status': 'error', 'error': '验证码错误'})
    # 验证邮箱是否存在
    conn = sqlite3.connect('./user_db/accounts_system.sqlite')
    c = conn.cursor()
    c.execute("SELECT * FROM users WHERE mail=?", (email,))
    user = c.fetchone()
    if user:
        # 登录成功，设置session
        session_code = str(random.randint(100000, 999999))
        session_map[session_code] = {'username': user[1], 'user_id': user[0]}
        # 更新登录时间和IP
        last_login_time = str(datetime.datetime.now())
        last_login_ip = get_remote_ip()
        c.execute("UPDATE users SET last_login_time=?, last_login_ip=? WHERE user_id=?", (last_login_time, last_login_ip, user[0]))
        conn.commit()
        return json.dumps({'status': 'ok','session_code': session_code})
    else:
        return json.dumps({'status': 'error', 'error': '邮箱不存在'})

@app.route('/check_login_code' , methods=['POST'])
def check_login_code():
    json_obj = json.loads(request.data.decode('utf-8'))
    session_code = json_obj['session_code']
    if session_code in session_map:
        return json.dumps({'status': 'ok'})
    else:
        return json.dumps({'status': 'error', 'error': '请先登录'})

app.run(debug=False, host='0.0.0.0', port=5500)
